package com.basics.api.service.impl;

import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.basics.api.request.channel.*;
import com.basics.api.response.channel.*;
import com.basics.api.response.organization.*;
import com.basics.api.service.ChannelApiService;
import com.basics.channel.entity.*;
import com.basics.common.exception.CustomException;
import com.basics.common.utils.AsyncUtil;
import com.basics.common.utils.StringUtils;
import com.basics.post.entity.CyChannelPost;
import com.basics.post.entity.CyChannelPostFile;
import com.basics.post.entity.CyChannelPostPrise;
import com.basics.user.entity.CyAuth;
import com.basics.user.entity.CyUser;
import org.apache.commons.collections4.CollectionUtils;
import org.apache.commons.collections4.MapUtils;
import org.springframework.beans.BeanUtils;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.util.ArrayList;
import java.util.Date;
import java.util.List;
import java.util.Map;

@Service
public class ChannelApiServiceImpl extends BaseApiService implements ChannelApiService {

    @Override
    public List<ChannelListData> selectHomeChannelList(Long organizationId, Long userId){
       return cyChannelService.selectHomeChannelList(organizationId,userId);
    }

    @Override
    public TopMsgData getTopMsgInfo(Long userId, Long channelId){
        TopMsgData data = new TopMsgData();
        PostOrMsgData msg = cyChannelMsgService.getLastMsg(channelId,userId);
        if(msg!=null){
            BeanUtils.copyProperties(msg,data);
        }

        data.setMsgNum(cyChannelMsgService.getUnReadMsgNum(channelId,userId));
        return data;
    }


    @Override
    public IPage<ChannelMsgListData> selectChannelMsgList(ChannelMshReq req, Long userId,Long organizationId){
        IPage<ChannelMsgListData> page = cyChannelMsgService.selectChannelMsgList(new Page(req.getPageNum(),req.getPageSize())
                ,req.getChannelId(),userId);
        if(CollectionUtils.isNotEmpty(page.getRecords())){
            page.getRecords().forEach(v->{
               if(v.getReceiveType()==1){
                   v.setHasPrise(cyChannelPostPriseService.checkHasPrise(userId,v.getReceiveItemId()));
                   if(v.getSendType()!=3){
                       v.setPriseNum(cyChannelPostPriseService.getPriseNum(Long.parseLong(v.getReceiveItemId())));
                   }

               }else{
                   v.setHasPrise(cyChannelCommentPriseService.checkHasPrise(userId,v.getReceiveItemId()));
                   if(v.getSendType()!=3) {
                       v.setPriseNum(cyChannelCommentPriseService.getPriseNum(v.getReceiveItemId()));
                   }
                   v.setIsMine(v.getReceiveUserId().equals(userId));
               }
            });
        }

        AsyncUtil.runAsync(()->{
            CyChannelMsg msg = new CyChannelMsg();
            msg.setReadFlag(1);
            cyChannelMsgService.update(msg,new QueryWrapper<CyChannelMsg>()
                            .eq("receive_user_id",userId)
                            .eq("read_flag",0)
                    .eq("channel_id",req.getChannelId()));

            pushReadMsg(req.getChannelId(),userId,organizationId);
        });
        return page;
    }

    @Override
    public ChannelInfoData getChannelInfo(Long channelId, Long userId){
        CyChannel cyChannel = cyChannelService.getById(channelId);
        ChannelInfoData data = new ChannelInfoData();
        data.setChannelName(cyChannel.getChannelName());
        data.setInviteUrl("https://xxxxxx?id="+cyChannel.getOrganizationId());
        data.setIsCreateUser(userId.equals(cyChannel.getCreateUserId()));
        data.setMemberNum(cyOrganizationUserService.getJoinMemberNum(cyChannel.getOrganizationId()));
        IPage<OrganizationMemberListData> memberPage = cyOrganizationUserService.selectJoinOrganizationMemberList(new Page<>(1,14),cyChannel.getOrganizationId(),null);
        data.setMemberList(memberPage.getRecords());
        CyChannelGroupUser channelGroupUser = cyChannelGroupUserService.getByChannelId(channelId,userId);
        if(channelGroupUser==null){
            channelGroupUser = new CyChannelGroupUser();
            channelGroupUser.setChannelId(channelId);
            channelGroupUser.setUserId(userId);
            channelGroupUser.setTopFlag(0);
            channelGroupUser.setDisturbFlag(0);
            cyChannelGroupUserService.save(channelGroupUser);
        }
        data.setDisturbFlag(channelGroupUser.getDisturbFlag());
        data.setTopFlag(channelGroupUser.getTopFlag());
        data.setOrganizationId(cyChannel.getOrganizationId());
        return data;
    }

    @Override
    public ChannelBaseInfoData getChannelBaseInfo(Long channelId){
        ChannelBaseInfoData data = new ChannelBaseInfoData();
        CyChannel cyChannel = cyChannelService.getById(channelId);
        data.setChannelName(cyChannel.getChannelName());
        data.setIcon(cyChannel.getIcon());
        data.setChannelType(cyChannel.getChannelType());
        data.setOrganizationName(cyOrganizationService.getById(cyChannel.getOrganizationId()).getOrganizationName());
        data.setCreateUserName(cyUserService.getById(cyChannel.getCreateUserId()).getNickName());
        data.setId(cyChannel.getId());
        return data;
    }

    @Override
    @Transactional
    public void setChannelInfo(SetChannelReq req, Long userId,Long organizationId){
        //checkHasChannelPermission(req.getChannelId(),userId);
        CyChannelGroupUser channelGroupUser = cyChannelGroupUserService.getByChannelId(req.getChannelId(),userId);
        if(channelGroupUser==null){
            channelGroupUser = new CyChannelGroupUser();
            channelGroupUser.setChannelId(req.getChannelId());
            channelGroupUser.setUserId(userId);
            channelGroupUser.setTopFlag(0);
            channelGroupUser.setDisturbFlag(0);
            cyChannelGroupUserService.save(channelGroupUser);
        }
        if(req.getDisturbFlag()!=null){
            channelGroupUser.setDisturbFlag(req.getDisturbFlag());
        }
        if(req.getTopFlag()!=null){
            channelGroupUser.setTopFlag(req.getTopFlag());
        }
        cyChannelGroupUserService.updateById(channelGroupUser);

        AsyncUtil.runAsync(()->{
            pushChannelMsg(req.getChannelId(),userId,organizationId);
        });
    }

    @Override
    public void setChannelPermission(SetChannelPermissionReq req, Long userId){
        checkHasChannelPermission(req.getChannelId(),userId);
        CyChannelPermission cyChannelPermission = cyChannelPermissionService.getByChannelId(req.getChannelId());
        if(cyChannelPermission==null){
            cyChannelPermission = new CyChannelPermission();
            cyChannelPermission.setChannelId(req.getChannelId());
            cyChannelPermission.setGroupIds(req.getGroupIds());
            cyChannelPermission.setNeedAuth(req.getNeedAuth());
            cyChannelPermissionService.save(cyChannelPermission);
        }else{
            cyChannelPermission.setGroupIds(req.getGroupIds());
            cyChannelPermission.setNeedAuth(req.getNeedAuth());
            cyChannelPermissionService.updateById(cyChannelPermission);
        }
    }

    @Override
    public ChannelPermissionData getChannelPermission(Long channelId, Long userId){
        ChannelPermissionData data = new ChannelPermissionData();
        CyChannelPermission cyChannelPermission = cyChannelPermissionService.getByChannelId(channelId);
        if(cyChannelPermission!=null){
            data.setGroupIds(cyChannelPermission.getGroupIds());
            data.setNeedAuth(cyChannelPermission.getNeedAuth());
        }else{
            data.setNeedAuth(false);
        }
        data.setGroupName(cyOrganizationGroupService.getByGroupIds(data.getGroupIds()));
        return data;
    }

    @Override
    public CheckHasPermissionViewChannelData checkHasPermissionViewChannel(Long channelId, Long userId){
        CheckHasPermissionViewChannelData data = new CheckHasPermissionViewChannelData();
        CyChannel cyChannel = cyChannelService.getById(channelId);
        if(userId.equals(cyChannel.getCreateUserId())){
            data.setHasPermission(true);
        }else{
            CyChannelPermission cyChannelPermission = cyChannelPermissionService.getByChannelId(channelId);
            if(cyChannelPermission==null){
                data.setHasPermission(false);
            }else{
                CyChannelGroupUser cyChannelGroupUser = cyChannelGroupUserService.getByChannelId(channelId,userId);
                if(cyChannelGroupUser==null){
                    data.setHasPermission(false);
                }else{
                    if(StringUtils.isNotEmpty(cyChannelPermission.getGroupIds()) &&
                            StringUtils.isNotEmpty(cyChannelGroupUser.getGroupId()) &&
                            cyChannelPermission.getGroupIds().contains(cyChannelGroupUser.getGroupId())){
                        if(cyChannelPermission.getNeedAuth()){
                            CyAuth auth = cyAuthService.getByUserId(userId);
                            if(auth!=null){
                                data.setHasPermission(true);
                            }
                        }else{
                            data.setHasPermission(true);
                        }

                    }
                }

            }

        }
        return data;
    }

    @Override
    public List<GroupListData> selectChannelGroupList(Long channelId){
        return cyChannelGroupService.selectChannelGroupList(channelId);
    }

    @Override
    public GroupChannelData getChannelGroupInfo(Long channelId, Long userId){
        CyChannel cyChannel = cyChannelService.getById(channelId);
        if(!userId.equals(cyChannel.getCreateUserId())){
            throw new CustomException("无权限查看");
        }
        GroupChannelData data = new GroupChannelData();
        data.setAllMember(cyChannelGroupUserService.getJoinMemberNum(cyChannel.getId()));
        data.setGroupList(cyChannelGroupService.selectGroupList(channelId));
        return data;
    }

    @Override
    public ChannelGroupInfoData getGroupDetail(String groupId, Long userId){
        ChannelGroupInfoData data = new ChannelGroupInfoData();
        CyChannelGroup group = cyChannelGroupService.getById(groupId);
        BeanUtils.copyProperties(group,data);
        data.setGroupPermissionList(cyChannelGroupPermissionService.selectByGroupId(groupId));
        data.setMemberNum(cyChannelGroupUserService.getMemberByGroupId(groupId));
        return data;
    }

    @Override
    @Transactional
    public void saveGroup(SaveGroupReq req, Long userId,Long organizationId){
        if(StringUtils.isNotEmpty(req.getGroupId())){
            CyChannelGroup group = cyChannelGroupService.getById(req.getGroupId());
            if(StringUtils.isNotEmpty(group.getGroupName())){
                group.setGroupName(req.getGroupName());
            }
            if(StringUtils.isNotEmpty(req.getIconColor())){
                group.setIconColor(req.getIconColor());
            }
            cyChannelGroupService.updateById(group);
            if(req.getGroupPermissionList()!=null){
                cyChannelGroupPermissionService.remove(new QueryWrapper<CyChannelGroupPermission>().eq("group_id",group.getId()));
                req.getGroupPermissionList().forEach(v->{
                    CyChannelGroupPermission permission = new CyChannelGroupPermission();
                    permission.setGroupId(group.getId());
                    permission.setPermission(v);
                    permission.setType(1);
                    cyChannelGroupPermissionService.save(permission);
                });
            }
        }else{
            CyChannelGroup group = new CyChannelGroup();
            group.setChannelId(req.getChannelId());
            group.setGroupName(req.getGroupName());
            group.setIconColor(req.getIconColor());
            group.setOrganizationId(organizationId);
            group.setDefaultFlag(false);
            group.setSortBy(cyChannelGroupService.count(new QueryWrapper<CyChannelGroup>().eq("channel_id", req.getChannelId()))+1);
            cyChannelGroupService.save(group);
            if(CollectionUtils.isNotEmpty(req.getGroupPermissionList())){
                req.getGroupPermissionList().forEach(v->{
                    CyChannelGroupPermission permission = new CyChannelGroupPermission();
                    permission.setGroupId(group.getId());
                    permission.setPermission(v);
                    permission.setType(1);
                    cyChannelGroupPermissionService.save(permission);
                });
            }
        }


    }

    @Override
    @Transactional
    public void deleteGroup(String groupId,Long userId){
        CyChannelGroup cyChannelGroup = cyChannelGroupService.getById(groupId);
        if(cyChannelGroup.getDefaultFlag()){
            throw new CustomException("默认分组不能删除");
        }
        checkHasChannelPermission(cyChannelGroup.getChannelId(),userId);
        List<CyChannelGroupUser> cyChannelGroupUsers = cyChannelGroupUserService.list(new QueryWrapper<CyChannelGroupUser>().eq("group_id", groupId));
        if(CollectionUtils.isNotEmpty(cyChannelGroupUsers)){
            CyChannelGroup defaultGroup = cyChannelGroupService.getDefaultGroup(cyChannelGroup.getChannelId());
            cyChannelGroupUsers.forEach(v->{
                if(defaultGroup!=null){
                    v.setGroupId(defaultGroup.getId());
                }
            });
            cyChannelGroupUserService.updateBatchById(cyChannelGroupUsers);
        }
        cyChannelGroupService.removeById(groupId);
    }

    @Override
    public void deleteTopic(String topicId,Long userId){
        CyChannelTopic cyChannelTopic = cyChannelTopicService.getById(topicId);
        if(cyChannelTopic.getDefaultFlag()!=null && cyChannelTopic.getDefaultFlag()==1){
            throw new CustomException("默认板块不能删除");
        }
        int len = cyChannelPostService.count(new QueryWrapper<CyChannelPost>().eq("topic_id",topicId));
        if(len>0){
            throw new CustomException("该板块有帖子，不能删除");
        }
        checkHasChannelPermission(cyChannelTopic.getChannelId(),userId);
        cyChannelTopic.setDelFlag(0);
        cyChannelTopicService.updateById(cyChannelTopic);
    }


    @Override
    @Transactional
    public void saveTopic(SaveTopicReq req,Long userId){
        checkHasChannelPermission(req.getChannelId(),userId);
        if(StringUtils.isNotEmpty(req.getId())){
            CyChannelTopic cyChannelTopic = cyChannelTopicService.getById(req.getId());
//            if(cyChannelTopic!=null && cyChannelTopic.getDefaultFlag()==1){
//                throw new CustomException("默认板块不能修改");
//            }
            cyChannelTopic.setTopicName(req.getTopicName());
            cyChannelTopic.setGroupIds(req.getGroupIds());
            cyChannelTopicService.updateById(cyChannelTopic);
        }else{
            CyChannelTopic cyChannelTopic = new CyChannelTopic();
            cyChannelTopic.setChannelId(req.getChannelId());
            cyChannelTopic.setTopicName(req.getTopicName());
            cyChannelTopic.setGroupIds(req.getGroupIds());
            cyChannelTopic.setDefaultFlag(0);
            cyChannelTopic.setSortBy(cyChannelTopicService.count(new QueryWrapper<CyChannelTopic>()
                    .eq("channel_id", req.getChannelId()))+1);
            cyChannelTopicService.save(cyChannelTopic);
        }
    }

    @Override
    public RuleData getChannelRule(Long channelId){
        CyChannelRule cyChannelRule = cyChannelRuleService.getByChannelId(channelId);
        RuleData data = new RuleData();
        if(cyChannelRule!=null){
            BeanUtils.copyProperties(cyChannelRule,data);
        }
        return data;
    }

    @Override
    public void saveChannelRule(RuleData req,Long userId){
        checkHasChannelPermission(req.getChannelId(),userId);
        CyChannelRule cyChannelRule = cyChannelRuleService.getByChannelId(req.getChannelId());
        if(cyChannelRule==null){
            cyChannelRule = new CyChannelRule();
            cyChannelRule.setChannelId(req.getChannelId());
            cyChannelRule.setAllowCode(req.getAllowCode());
            cyChannelRule.setKeywords(req.getKeywords());
            cyChannelRule.setAllowUrl(req.getAllowUrl());
            cyChannelRuleService.save(cyChannelRule);
        }else{
            cyChannelRule.setAllowCode(req.getAllowCode());
            cyChannelRule.setKeywords(req.getKeywords());
            cyChannelRule.setAllowUrl(req.getAllowUrl());
            cyChannelRuleService.updateById(cyChannelRule);
        }
    }


    @Override
    public IPage<GroupOrganizationMemberListData> selectChannelGroupMemberList(GroupChannelMemberReq req, Long userId){
        IPage<GroupOrganizationMemberListData> page = cyChannelGroupUserService.selectChannelGroupMemberList(req);
        if(CollectionUtils.isNotEmpty(page.getRecords())){
            page.getRecords().forEach(v->{
                v.setGroupNum(cyChannelGroupUserService.getGroupMemberNum(v.getGroupId()));
            });
        }
        return page;
    }

    @Override
    public void addGroupChannel(OperateGroupChannelReq req,Long userId){
        CyChannelGroup group = cyChannelGroupService.getById(req.getGroupId());
        if(group==null){
            throw new CustomException("分组不存在");
        }
        CyChannelGroupUser groupUser = cyChannelGroupUserService.getOne(new QueryWrapper<CyChannelGroupUser>()
                .eq("user_id",req.getUserId()).eq("group_id",req.getGroupId()));
        if(groupUser!=null){
            groupUser.setGroupId(req.getGroupId());
            cyChannelGroupUserService.updateById(groupUser);
        }
    }

    public void removeGroupChannel(OperateGroupChannelReq req,Long userId){
        CyChannelGroup group = cyChannelGroupService.getById(req.getGroupId());
        if(group==null){
            throw new CustomException("分组不存在");
        }
        if(group.getDefaultFlag()){
            throw new CustomException("默认分组不能删除");
        }
        CyChannelGroupUser groupUser = cyChannelGroupUserService.getOne(new QueryWrapper<CyChannelGroupUser>()
                .eq("user_id",req.getUserId()).eq("group_id",req.getGroupId()));
        if(groupUser==null){
            throw new CustomException("该用户未加入该分组");
        }

        CyChannelGroup defaultGroup = cyChannelGroupService.getDefaultGroup(group.getChannelId());
        if(defaultGroup!=null){
            groupUser.setGroupId(defaultGroup.getId());
        }
        cyChannelGroupUserService.updateById(groupUser);
    }

    private void checkHasChannelPermission(Long channelId,Long userId){
        CyChannel cyChannel = cyChannelService.getById(channelId);
        if(!userId.equals(cyChannel.getCreateUserId())){
            throw new CustomException("无权限操作");
        }
    }
}
